package com.hsjk.szwj.module.pay.service;

import cn.hutool.core.util.StrUtil;
import com.github.binarywang.wxpay.bean.entpay.EntPayQueryResult;
import com.github.binarywang.wxpay.bean.entpay.EntPayRequest;
import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
import com.github.binarywang.wxpay.bean.transfer.TransferBatchDetailResult;
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest;
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.hsjk.szwj.framework.common.constant.CommonConstant;
import com.hsjk.szwj.module.pay.controller.app.transfer.vo.TransferOrderReqVO;
import com.hsjk.szwj.module.pay.dal.dataobject.config.ChannelRetMsg;
import com.hsjk.szwj.module.pay.dal.dataobject.config.MchAppConfigContext;
import com.hsjk.szwj.module.pay.dal.dataobject.config.WxServiceWrapper;
import com.hsjk.szwj.module.pay.dal.dataobject.order.TransferOrderDO;
import com.hsjk.szwj.module.pay.enums.IfCodeEnum;
import com.hsjk.szwj.module.pay.enums.MchTypeEnum;
import com.hsjk.szwj.module.pay.enums.WxPayVersionEnum;
import com.hsjk.szwj.module.pay.util.WxpayKit;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author chenjiawei
 * @desc 转账接口： 微信官方
 * @Date 2023/08/26 15:13
 **/
@Slf4j
@Service
public class WxpayTransferService implements ITransferService {
    @Resource
    private ConfigContextQueryService configContextQueryService;

    @Override
    public String getIfCode() {
        return IfCodeEnum.WXPAY.getCode();
    }

    @Override
    public boolean isSupport(String entryType) {
        // 微信仅支持 零钱 和 银行卡入账方式
        if (CommonConstant.ENTRY_WX_CASH.equals(entryType)
                || CommonConstant.ENTRY_BANK_CARD.equals(entryType)) {
            return true;
        }
        return false;
    }

    @Override
    public String preCheck(TransferOrderReqVO bizRQ, TransferOrderDO transferOrder) {
        /**
         * 微信企业付款到零钱 产品：不支持服务商模式，参考如下链接：
         * https://developers.weixin.qq.com/community/develop/doc/0004888f8603b042a45c632355a400?highLine=%25E4%25BB%2598%25E6%25AC%25BE%25E5%2588%25B0%25E9%259B%25B6%25E9%2592%25B1%2520%2520%25E6%259C%258D%25E5%258A%25A1%25E5%2595%2586
         * 微信官方解答： 目前企业付款到零钱，是不支持服务商模式的哈，如果特约商户需要使用该功能，请自行登录商户平台申请使用。
         **/
        if (MchTypeEnum.ISVSUB.getValue().equals(transferOrder.getMchType())) {
            return "微信子商户暂不支持转账业务";
        }

        return null;
    }

    @Override
    public ChannelRetMsg transfer(TransferOrderReqVO bizRQ,
                                  TransferOrderDO transferOrder,
                                  MchAppConfigContext mchAppConfigContext) throws Exception {

        try {

            WxServiceWrapper wxServiceWrapper =
                    configContextQueryService.getWxServiceWrapper(mchAppConfigContext);

            if (WxPayVersionEnum.WX_V2.getVersion()
                    .equals(wxServiceWrapper.getApiVersion())) {
                //V2

                EntPayRequest request = new EntPayRequest();
                // 商户账号appid
                request.setMchAppid(wxServiceWrapper.getWxPayService().getConfig().getAppId());
                //商户号
                request.setMchId(wxServiceWrapper.getWxPayService().getConfig().getMchId());
                //商户订单号
                request.setPartnerTradeNo(String.valueOf(transferOrder.getId()));
                //openid
                request.setOpenid(transferOrder.getAccountNo());
                //付款金额，单位为分
                request.setAmount(Math.toIntExact(transferOrder.getAmount()));
                request.setSpbillCreateIp(transferOrder.getClientIp());
                //付款备注
                request.setDescription(transferOrder.getTransferDesc());
                if (StringUtils.isNotEmpty(transferOrder.getAccountName())) {
                    request.setReUserName(transferOrder.getAccountName());
                    request.setCheckName("FORCE_CHECK");
                } else {
                    request.setCheckName("NO_CHECK");
                }

                EntPayResult entPayResult = wxServiceWrapper.getWxPayService()
                        .getEntPayService().entPay(request);
                return ChannelRetMsg.waiting();

            } else if (WxPayVersionEnum.WX_V3.getVersion()
                    .equals(wxServiceWrapper.getApiVersion())) {
                TransferBatchesRequest request = new TransferBatchesRequest();
                request.setAppid(wxServiceWrapper.getWxPayService().getConfig().getAppId());
                request.setOutBatchNo(String.valueOf(transferOrder.getId()));
                String batchName = "szwj-" + System.currentTimeMillis();
                request.setBatchName(batchName);
                request.setBatchRemark(transferOrder.getTransferDesc());
                request.setTotalAmount(Math.toIntExact(transferOrder.getAmount()));
                request.setTotalNum(1);

                List<TransferBatchesRequest.TransferDetail> list = new ArrayList<>();
                TransferBatchesRequest.TransferDetail transferDetail =
                        new TransferBatchesRequest.TransferDetail();
                transferDetail.setOutDetailNo(String.valueOf(transferOrder.getId()));
                transferDetail.setOpenid(transferOrder.getAccountNo());
                //付款金额，单位为分
                transferDetail.setTransferAmount(Math.toIntExact(transferOrder.getAmount()));
                transferDetail.setUserName(transferOrder.getAccountName());
                transferDetail.setTransferRemark(transferOrder.getTransferDesc());
                list.add(transferDetail);
                request.setTransferDetailList(list);

                TransferBatchesResult transferBatchesResult
                        = wxServiceWrapper.getWxPayService().getTransferService()
                        .transferBatches(request);
                if (StrUtil.isNotEmpty(transferBatchesResult.getBatchId())) {
                    return ChannelRetMsg.confirmSuccess(transferBatchesResult.getBatchId());
                }
                return ChannelRetMsg.waiting();
            } else {
                return ChannelRetMsg.sysError("请选择微信V2或V3模式");
            }

        } catch (WxPayException e) {

            //出现未明确的错误码时（SYSTEMERROR等），请务必用原商户订单号重试，或通过查询接口确认此次付款的结果。
            if ("SYSTEMERROR".equalsIgnoreCase(e.getErrCode())) {
                return ChannelRetMsg.waiting();
            }
            return ChannelRetMsg.confirmFail(null,
                    WxpayKit.appendErrCode(e.getReturnMsg(), e.getErrCode()),
                    WxpayKit.appendErrMsg(e.getReturnMsg(), StringUtils.defaultIfEmpty(e.getErrCodeDes(), e.getCustomErrorMsg())));

        } catch (Exception e) {
            log.error("转账异常：", e);
            return ChannelRetMsg.waiting();
        }
    }

    @Override
    public ChannelRetMsg query(TransferOrderDO transferOrder, MchAppConfigContext mchAppConfigContext) {

        try {
            WxServiceWrapper wxServiceWrapper = configContextQueryService.getWxServiceWrapper(mchAppConfigContext);

            if (WxPayVersionEnum.WX_V2.getVersion()
                    .equals(wxServiceWrapper.getApiVersion())) {
                //V2

                EntPayQueryResult entPayQueryResult =
                        wxServiceWrapper.getWxPayService().getEntPayService()
                                .queryEntPay(String.valueOf(transferOrder.getId()));

                // SUCCESS，明确成功
                if ("SUCCESS".equalsIgnoreCase(entPayQueryResult.getStatus())) {
                    return ChannelRetMsg.confirmSuccess(entPayQueryResult.getDetailId());
                } else if ("FAILED".equalsIgnoreCase(entPayQueryResult.getStatus())) {
                    // FAILED，明确失败
                    return ChannelRetMsg.confirmFail(entPayQueryResult.getStatus(),
                            entPayQueryResult.getReason());
                } else {
                    return ChannelRetMsg.waiting();
                }
            } else if (WxPayVersionEnum.WX_V3.getVersion()
                    .equals(wxServiceWrapper.getApiVersion())) {

                TransferBatchDetailResult transferBatchDetailResult =
                        wxServiceWrapper.getWxPayService().getTransferService().
                                transferBatchesOutBatchNoDetail(String.valueOf(transferOrder.getId()),
                                        String.valueOf(transferOrder.getId()));

                // SUCCESS，明确成功
                if ("SUCCESS".equalsIgnoreCase(transferBatchDetailResult.getDetailStatus())) {
                    return ChannelRetMsg.confirmSuccess(transferBatchDetailResult.getDetailId());
                } else if ("FAIL".equalsIgnoreCase(transferBatchDetailResult.getDetailStatus())) {
                    // FAIL，明确失败
                    return ChannelRetMsg.confirmFail(transferBatchDetailResult.getDetailStatus(), transferBatchDetailResult.getFailReason());
                } else {
                    return ChannelRetMsg.waiting();
                }
            } else {
                return ChannelRetMsg.sysError("请选择微信V2或V3模式");
            }

        } catch (WxPayException e) {

            // 如果查询单号对应的数据不存在，那么数据不存在的原因可能是：（1）付款还在处理中；（2）付款处理失败导致付款订单没有落地，务必再次查询确认此次付款的结果。
            if ("NOT_FOUND".equalsIgnoreCase(e.getErrCode())) {
                return ChannelRetMsg.waiting();
            }

            return ChannelRetMsg.confirmFail(null,
                    WxpayKit.appendErrCode(e.getReturnMsg(), e.getErrCode()),
                    WxpayKit.appendErrMsg(e.getReturnMsg(), StringUtils.defaultIfEmpty(e.getErrCodeDes(), e.getCustomErrorMsg())));

        } catch (Exception e) {
            log.error("转账状态查询异常：", e);
            return ChannelRetMsg.waiting();
        }
    }
}
